#include "GPUFramework.h"




/************************************************************************/
/* GL Initialize Operation                                              */
/************************************************************************/

GLuint glInitial(int* argc, char **argv)
{
	GLuint window;
	glutInit ( argc, argv );
	window=glutCreateWindow("GPGPU");
	glewInit();
	return window;
}

/************************************************************************/
/* Create and Bind FBO                                                  */
/************************************************************************/

void createFBO(GLuint* fb)
{
	glGenFramebuffersEXT(1, fb); 
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fb);
}

/************************************************************************/
/* Configure Culling Space                                              */
/************************************************************************/

void configureCullingSpace(int width,int height)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, width, 0.0, height);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glViewport(0, 0, width, height);
}

/************************************************************************/
/* Create and Configure Textures                                        */
/************************************************************************/

void createTexture(GLuint* tID,int width,int height,texInfo* tex)
{
	glGenTextures(1,tID);

	glBindTexture(tex->target,*tID);
	glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexImage2D(tex->target,0,tex->internalFormat,width,height,0,tex->format,GL_FLOAT,0);
}

/************************************************************************/
/* Send Texture to Visual Memory                                        */
/************************************************************************/

void sendTexture(int width,int height,texInfo* tex,float* data)
{
	glTexSubImage2D(tex->target,0,0,0,width,height,tex->format,GL_FLOAT,data);
}

/************************************************************************/
/* Initialize Nvidia Cg Environment                                     */
/************************************************************************/

void cgInitial(CGcontext* cgContext,CGprofile* fragmentProfile,CGprogram* fragmentProgram,char* sourceFile)
{
	*cgContext = cgCreateContext();
	*fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
	cgGLSetOptimalOptions(*fragmentProfile);
	*fragmentProgram = cgCreateProgramFromFile (*cgContext, CG_SOURCE, sourceFile, *fragmentProfile, 0, 0);
	cgGLLoadProgram (*fragmentProgram);
}

/************************************************************************/
/* Initialize Nvidia Cg Parameter                                       */
/************************************************************************/

void cgParamInitial(CGparameter* data,char* paramName,CGprogram* fragmentProgram)
{
	*data = cgGetNamedParameter (*fragmentProgram, paramName);
}

/************************************************************************/
/* Initialize Essential Buffers                                         */
/************************************************************************/

void bufferInitial(GLuint* tID,texInfo* tex,CGprofile* fragmentProfile,CGprogram* fragmentProgram)
{
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, tex->target, *tID, 0);
	cgGLEnableProfile(*fragmentProfile);
	cgGLBindProgram(*fragmentProgram);
	glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
}

/************************************************************************/
/* Configure Essential Texture Parameter                                */
/************************************************************************/

void cgTexParamConfigure(GLuint* tID,CGparameter* data)
{
	cgGLSetTextureParameter(*data, *tID);
	cgGLEnableTextureParameter(*data);
}

/************************************************************************/
/* Trigger GPU Computation                                              */
/************************************************************************/

void triggerGPUComputation(int width,int height)
{
	glPolygonMode(GL_FRONT,GL_FILL);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0, 0.0); 
	glVertex2f(0.0, 0.0);
	glTexCoord2f(width, 0.0); 
	glVertex2f(width, 0.0);
	glTexCoord2f(width, height); 
	glVertex2f(width, height);
	glTexCoord2f(0.0, height); 
	glVertex2f(0.0, height);
	glEnd();
}

/************************************************************************/
/* Read Buffers to Get the Feedback                                     */
/************************************************************************/

void readBuffer(int width,int height,texInfo* tex,float*data)
{
	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
	glReadPixels(0, 0, width, height,tex->format,GL_FLOAT,data);
}

/************************************************************************/
/* Release Nvidia Cg Resource                                           */
/************************************************************************/

void cgRelease(CGcontext* cgContext,CGprogram* fragmentProgram)
{
	cgDestroyProgram(*fragmentProgram);
	cgDestroyContext(*cgContext);
}

/************************************************************************/
/* Release FBO Resource                                                 */
/************************************************************************/

void FBORelease(GLuint* fb)
{
	glDeleteFramebuffersEXT(1,fb);
}

/************************************************************************/
/* Release Texture Resource                                             */
/************************************************************************/

void textureRelease(GLuint* tID)
{
	glDeleteTextures(1,tID);
}

/************************************************************************/
/* Release GL Resource                                                  */
/************************************************************************/

void glRelease(GLuint* window)
{
	glutDestroyWindow (*window);
}